﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Example6_Particles.View
{
    class StatefullSpraySystem
    {
        private const int NUM_PARTICLES = 1000;

        Vector2[] m_spawnPositions = new Vector2[NUM_PARTICLES];
        Vector2[] m_spawnSpeed = new Vector2[NUM_PARTICLES];


        float m_oldTime = 0.0f;
        Vector2 m_oldSpawnPos = new Vector2();

        public StatefullSpraySystem()
        {
            for (int i = 0; i < NUM_PARTICLES; i++)
            {
                m_spawnPositions[i] = new Vector2();
                m_spawnSpeed[i] = new Vector2();
            }
        }

        public void DrawSpray(float a_elapsedTime, 
                              Vector2 a_spawnModelPosition,
                              Vector2 a_spawnModelSpeed,                   
                              Vector2 a_viewPosition, 
                              
                              float a_viewScale, 
                              SpriteBatch a_batch, 
                              Texture2D a_texture)
        {
            for (int i = 0; i < NUM_PARTICLES; i++)
            {
                //Get the individual time for this particle i
                float particleTime = GetParticleTime(i, a_elapsedTime);
                float particleOldTime = GetParticleTime(i, m_oldTime);
                
                //Get the max time for particle i
                float maxTime = GetParticleMaxTime(i);
                float percentLife = particleTime / maxTime;

                //all particles rotate the same
                float rotationalSpeed = 0.25f;

                if (particleTime < particleOldTime)
                {
                    float elapsedTime = a_elapsedTime - m_oldTime;
                    float timeWhenSpawned = elapsedTime - particleTime;
                    float timeWhenSpawnedPercent = timeWhenSpawned / elapsedTime;

                    //copy the speed from input 
                    m_spawnPositions[i].X = m_oldSpawnPos.X * timeWhenSpawnedPercent + a_spawnModelPosition.X * (1 - timeWhenSpawnedPercent);
                    m_spawnPositions[i].Y = m_oldSpawnPos.Y * timeWhenSpawnedPercent + a_spawnModelPosition.Y * (1 - timeWhenSpawnedPercent);
                    m_spawnSpeed[i].X = a_spawnModelSpeed.X;
                    m_spawnSpeed[i].Y = a_spawnModelSpeed.Y;
                }


                //interpolate from 1 to 0 depending on time for this particle
                float percentLeft = 1.0f - particleTime / maxTime;

                //different sizes depending on index (i % 80) and a minimum size of 10 and particles are growing with respect to time
                float size = 10;// 50 * (1.0f - particleTime / maxTime);
                float rotation = particleTime * 2.0f * (float)Math.PI / maxTime * rotationalSpeed + (float)i;

                //Get The View Position for the individual particle i relative
                Vector2 viewPos = GetPosition(i, particleTime) * a_viewScale + a_viewPosition;
                DrawParticleAt(viewPos, size, percentLeft, a_batch, a_texture, rotation);
                
                
                
            }
            m_oldTime = a_elapsedTime;
            m_oldSpawnPos = a_spawnModelPosition;
        }

        //interpolate a position
        private Vector2 GetPosition(int i, float a_elapsedTime)
        {
            //all smoke particles accelerate upwards
            Vector2 acceleration = new Vector2(0, 0.5f);

            return m_spawnPositions[i] + (m_spawnSpeed[i]) * a_elapsedTime +acceleration * a_elapsedTime * a_elapsedTime;
        }

        private void DrawParticleAt(Vector2 a_viewPos, float a_size, float a_alpha, SpriteBatch a_batch, Texture2D a_texture, float a_rotation)
        {
            //the entire texture as source
            Rectangle srcRect = new Rectangle(0, 0, a_texture.Width, a_texture.Height);

            //color fades to 0
            Color color = new Color(a_alpha * 1.0f, 1.0f * a_alpha, 1.0f * a_alpha, a_alpha);

            //rotate around middle of texture
            Vector2 origin = new Vector2(a_texture.Width / 2, a_texture.Height / 2);

            //size is relative to texture size in draw
            float size = a_size / a_texture.Width;

            //and draw it
            a_batch.Draw(a_texture, a_viewPos, srcRect, color, a_rotation, origin, size, SpriteEffects.None, 0);

        }

        //this is how long a particle lives in seconds
        private float GetParticleMaxTime(int i)
        {
            Random rand = new Random(i);
            return (float)rand.NextDouble()*0.75f + 0.01f;
        }


        private float GetParticleTime(int i, float a_totalTime)
        {
            
            //calculate how many times a particle has existed
            float times = (int)(a_totalTime / GetParticleMaxTime(i)); //how many rotations

            //remove the previous times from time
            return a_totalTime - times * GetParticleMaxTime(i);
        }
    }
}
